package raft

type smfollower struct {
	rf *Raft
}

func (follower *smfollower) enter(oldstate State, isnewterm bool) {
}

func (follower *smfollower) recvAppend(args *RequestAppendArgs, reply *RequestAppendReply) {
	rf := follower.rf
	reply.Term = rf.persistentContext.CurrentTerm
	index := rf.persistentContext.GetLastIndex()

	if args.PrevLogIndex < rf.persistentContext.SnapshotIndex {
		reply.Success = true
		return
	}

	if args.PrevLogIndex > index || rf.persistentContext.GetEntryTerm(args.PrevLogIndex) != args.PrevLogTerm {
		reply.Success = false

		if args.PrevLogIndex > index {
			reply.XIndex = index + 1
			reply.XTerm = -1
		} else {
			i := args.PrevLogIndex
			reply.XTerm = rf.persistentContext.GetEntryTerm(i)
			for ; i > rf.commitIndex+1 && rf.persistentContext.GetEntryTerm(i-1) == reply.XTerm; i-- {

			}
			reply.XIndex = i
		}

		rf.Log("TRCE", "fail to append, index:%d ,indexTerm:%d.", index, rf.persistentContext.GetEntryTerm(index))
		return
	}
	reply.Success = true
	rf.Log("TRCE", "success append")
	follower.appendLogs(args.Entries, args.PrevLogIndex+1)

	if args.LeaderCommit > rf.commitIndex {

		rf.commitIndex = Min(args.LeaderCommit, rf.persistentContext.GetLastIndex())
		rf.cond.Signal()
	}
}

func (follower *smfollower) appendLogs(entries []LogEntry, sp EntryIndex) {
	cnt := 0
	for _, v := range entries {
		if follower.rf.persistentContext.GetLastIndex() >= sp && follower.rf.persistentContext.GetEntryTerm(sp) == v.Term {
			sp++
			continue
		}
		follower.rf.appendLog(v, sp)
		sp++
		cnt++
	}
	if cnt > 0 {
		follower.rf.needPersist = true
	}
}
